<script setup lang="ts">
import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
import { message } from 'ant-design-vue';
import { CopyOutlined, FormatPainterOutlined } from '@ant-design/icons-vue';
import * as monaco from 'monaco-editor';
import loader from '@monaco-editor/loader';

interface Props {
  modelValue?: string;
  language?: 'groovy' | 'json' | 'sql' | 'javascript';
  height?: number;
  readonly?: boolean;
  placeholder?: string;
  autoFormatOnMount?: boolean;
}

interface Emits {
  (e: 'update:modelValue', value: string): void;
}

const props = withDefaults(defineProps<Props>(), {
  modelValue: '',
  language: 'javascript',
  height: 200,
  readonly: false,
  placeholder: '请输入代码...',
  autoFormatOnMount: false
});

const emit = defineEmits<Emits>();

const editorContainer = ref<HTMLElement>();
let editor: monaco.editor.IStandaloneCodeEditor | null = null;

// 配置Monaco Editor
loader.config({
  paths: {
    vs: 'https://cdn.jsdelivr.net/npm/monaco-editor@0.52.2/min/vs'
  }
});

// 语言映射
const getMonacoLanguage = (lang: string) => {
  switch (lang) {
    case 'groovy':
      return 'java'; // Groovy使用Java语法高亮
    case 'json':
      return 'json';
    case 'sql':
      return 'sql';
    case 'javascript':
      return 'javascript';
    default:
      return 'plaintext';
  }
};

// SQL格式化逻辑
const formatSQL = (code: string) => {
  // SQL关键字列表
  const sqlKeywords = [
    'SELECT',
    'FROM',
    'WHERE',
    'JOIN',
    'INNER JOIN',
    'LEFT JOIN',
    'RIGHT JOIN',
    'FULL JOIN',
    'GROUP BY',
    'ORDER BY',
    'HAVING',
    'UNION',
    'INSERT',
    'UPDATE',
    'DELETE',
    'CREATE',
    'ALTER',
    'DROP'
  ];

  let formatted = code
    // 移除多余的空格
    .replace(/\s+/g, ' ')
    .trim();

  // 在主要SQL关键字前添加换行
  sqlKeywords.forEach(keyword => {
    const regex = new RegExp(`\\b${keyword}\\b`, 'gi');
    formatted = formatted.replace(regex, `\n${keyword}`);
  });

  // 处理逗号后的换行（在SELECT子句中）
  formatted = formatted.replace(/,\s*(?=\w)/g, ',\n    ');

  // 清理开头的换行符
  formatted = formatted.replace(/^\n+/, '');

  // 添加适当的缩进
  const lines = formatted.split('\n');
  const formattedLines = lines.map(line => {
    const trimmed = line.trim();
    if (!trimmed) return '';

    // 主要关键字不缩进
    if (sqlKeywords.some(keyword => trimmed.toUpperCase().startsWith(keyword.toUpperCase()))) {
      return trimmed;
    }

    // 其他行缩进4个空格
    return `    ${trimmed}`;
  });

  return formattedLines.join('\n');
};

// Groovy格式化逻辑
const formatGroovy = (code: string) => {
  // 预处理：保护字符串字面量
  const stringLiterals: string[] = [];
  let processedCode = code.replace(/(['"`])(?:(?!\1)[^\\]|\\.)*\1/g, match => {
    const index = stringLiterals.length;
    stringLiterals.push(match);
    return `__STRING_LITERAL_${index}__`;
  });

  // 基本格式化规则
  processedCode = processedCode
    // 在分号后添加换行符
    .replace(/;\s*(?=\S)/g, ';\n')
    // 在左大括号前添加空格，后添加换行符
    .replace(/\s*\{\s*/g, ' {\n')
    // 在右大括号前后添加换行符
    .replace(/\s*\}\s*/g, '\n}\n')
    // 处理switch语句的case
    .replace(/(case\s+[^:]+:|default\s*:)\s*/g, '$1\n')
    // 处理break语句
    .replace(/break\s*;/g, 'break;')
    // 清理多余的空行
    .replace(/\n\s*\n\s*\n/g, '\n\n')
    .replace(/^\n+|\n+$/g, '');

  const lines = processedCode.split('\n');
  let indentLevel = 0;
  const indentSize = 4;
  let inSwitch = false;
  let switchIndentLevel = 0;

  const formattedLines = lines.map(line => {
    const trimmedLine = line.trim();

    // 空行保持空行
    if (!trimmedLine) return '';

    // 检测switch语句开始
    if (trimmedLine.includes('switch(')) {
      inSwitch = true;
      switchIndentLevel = indentLevel;
    }

    // 处理右大括号（减少缩进）
    if (trimmedLine.startsWith('}')) {
      indentLevel = Math.max(0, indentLevel - 1);
      if (inSwitch && indentLevel <= switchIndentLevel) {
        inSwitch = false;
      }
    }

    // 确定当前行的缩进级别
    let currentIndent = indentLevel;

    // case和default语句的特殊处理
    if (inSwitch && (trimmedLine.startsWith('case ') || trimmedLine.startsWith('default:'))) {
      currentIndent = switchIndentLevel + 1;
    }

    // 生成缩进后的行
    const indentedLine = ' '.repeat(currentIndent * indentSize) + trimmedLine;

    // 处理左大括号（增加缩进）
    if (trimmedLine.endsWith('{')) {
      indentLevel += 1;
    }

    return indentedLine;
  });

  let result = formattedLines.join('\n');

  // 恢复字符串字面量
  stringLiterals.forEach((literal, index) => {
    result = result.replace(`__STRING_LITERAL_${index}__`, literal);
  });

  return result;
};

// 自定义格式化逻辑
const customFormat = () => {
  if (!editor) return;

  const originalValue = editor.getValue();
  let formattedCode = '';

  // 根据语言类型选择不同的格式化策略
  if (props.language === 'sql') {
    formattedCode = formatSQL(originalValue);
  } else if (props.language === 'groovy') {
    formattedCode = formatGroovy(originalValue);
  } else {
    // 其他语言使用简单的格式化
    formattedCode = formatGroovy(originalValue);
  }

  if (formattedCode !== originalValue) {
    editor.setValue(formattedCode);
    message.success('代码格式化成功');
  } else {
    message.info('代码已经是格式化状态');
  }
};

// 格式化代码
const formatCode = async () => {
  if (!editor) {
    message.error('编辑器未初始化');
    return;
  }

  const originalValue = editor.getValue();
  console.log('格式化前的内容:', originalValue);
  console.log('当前语言:', props.language);

  if (!originalValue.trim()) {
    message.warning('没有内容需要格式化');
    return;
  }

  try {
    if (props.language === 'json') {
      // JSON格式化
      const parsed = JSON.parse(originalValue);
      const formatted = JSON.stringify(parsed, null, 2);
      if (formatted !== originalValue) {
        editor.setValue(formatted);
        message.success('JSON格式化成功');
      } else {
        message.info('JSON已经是格式化状态');
      }
    } else {
      // 尝试使用Monaco Editor的内置格式化
      const formatAction = editor.getAction('editor.action.formatDocument');
      console.log('格式化动作是否存在:', Boolean(formatAction));

      if (formatAction) {
        const beforeFormat = editor.getValue();
        await formatAction.run();
        const afterFormat = editor.getValue();

        if (beforeFormat !== afterFormat) {
          message.success('代码格式化成功');
        } else {
          // Monaco Editor格式化没有效果，使用自定义格式化
          console.log('Monaco Editor格式化无效果，使用自定义格式化');
          customFormat();
        }
      } else {
        // 直接使用自定义格式化
        customFormat();
      }
    }
  } catch (error) {
    console.error('格式化错误:', error);
    if (props.language === 'json') {
      message.error('JSON格式错误，无法格式化');
    } else {
      message.error(`代码格式化失败: ${(error as Error).message}`);
    }
  }
};

// 复制代码
const copyCode = async () => {
  if (!editor) return;

  try {
    const value = editor.getValue();
    await navigator.clipboard.writeText(value);
    message.success('代码已复制到剪贴板');
  } catch {
    message.error('复制失败');
  }
};

// 初始化编辑器
const initEditor = async () => {
  if (!editorContainer.value) return;

  try {
    const monacoInstance = await loader.init();

    editor = monacoInstance.editor.create(editorContainer.value, {
      value: props.modelValue || '',
      language: getMonacoLanguage(props.language),
      theme: 'vs-dark',
      automaticLayout: true,
      minimap: { enabled: false },
      scrollBeyondLastLine: false,
      wordWrap: 'on',
      readOnly: props.readonly,
      fontSize: 14,
      lineNumbers: 'on',
      folding: true,
      autoIndent: 'full',
      formatOnPaste: true,
      formatOnType: true,
      placeholder: props.placeholder
    });

    // 监听内容变化
    editor.onDidChangeModelContent(() => {
      if (editor) {
        emit('update:modelValue', editor.getValue());
      }
    });

    // 如果启用了自动格式化，在编辑器初始化后自动格式化
    if (props.autoFormatOnMount && props.modelValue && props.modelValue.trim()) {
      // 使用nextTick确保编辑器完全初始化
      await nextTick();
      setTimeout(() => {
        formatCode();
      }, 100);
    }
  } catch (error) {
    console.error('Monaco Editor初始化失败:', error);
    message.error('代码编辑器初始化失败');
  }
};

// 监听语言变化
watch(
  () => props.language,
  newLang => {
    if (editor) {
      const model = editor.getModel();
      if (model) {
        monaco.editor.setModelLanguage(model, getMonacoLanguage(newLang));
      }
    }
  }
);

// 监听值变化
watch(
  () => props.modelValue,
  newValue => {
    if (editor && editor.getValue() !== (newValue || '')) {
      editor.setValue(newValue || '');
    }
  }
);

// 监听只读状态变化
watch(
  () => props.readonly,
  readonly => {
    if (editor) {
      editor.updateOptions({ readOnly: readonly });
    }
  }
);

onMounted(async () => {
  await nextTick();
  await initEditor();
});

onUnmounted(() => {
  if (editor) {
    editor.dispose();
    editor = null;
  }
});
</script>

<template>
  <div class="code-editor">
    <div class="editor-toolbar">
      <AButton size="small" @click="formatCode">
        <template #icon><FormatPainterOutlined /></template>
        格式化
      </AButton>
      <AButton size="small" @click="copyCode">
        <template #icon><CopyOutlined /></template>
        复制
      </AButton>
    </div>
    <div ref="editorContainer" class="editor-container" :style="{ height: height + 'px' }"></div>
  </div>
</template>

<style scoped>
.code-editor {
  border: 1px solid #d9d9d9;
  border-radius: 6px;
  overflow: hidden;
}

.editor-toolbar {
  display: flex;
  gap: 8px;
  padding: 8px 12px;
  background-color: #fafafa;
  border-bottom: 1px solid #d9d9d9;
}

.editor-container {
  width: 100%;
}

/* 深色主题下的样式调整 */
.code-editor :deep(.monaco-editor) {
  border-radius: 0 0 6px 6px;
}

.code-editor :deep(.monaco-editor .margin) {
  background-color: #1e1e1e;
}

.code-editor :deep(.monaco-editor .monaco-editor-background) {
  background-color: #1e1e1e;
}
</style>
